package com.kevis.zhunblog.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.github.pagehelper.PageInfo;
import com.kevis.zhunblog.core.dto.PageDomain;
import com.kevis.zhunblog.core.dto.query.CommonClassQuery;
import com.kevis.zhunblog.core.entities.BaseClassEntity;
import com.kevis.zhunblog.service.CommonClassService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;

import javax.annotation.Resource;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * CommonClassServiceImpl
 * Author kevis
 * Date 2023/4/20 16:53
 */
//public class CommonClassServiceImpl<M extends BaseMapper<T>, T extends BaseClassEntity> extends ServiceImpl<M, T> implements CommonClassService<T> {
public class CommonClassServiceImpl<M extends BaseMapper<T>, T extends BaseClassEntity> extends BaseCommonServiceImpl<M, T> implements CommonClassService<T> {
    //ServiceImpl<M, T> implements CommonClassService<T>

    //@Override
//    public PageInfo<BaseClassEntity> getPageList(CommonClassQuery query, PageDomain pageDomain) {
//        return null;
//    }

//    @Autowired
//    RedisTemplate redisTemplate;

    //@Lazy
    @Resource
    //@Qualifier(value = "redisTemplate1")
    RedisTemplate<String, Object> redisTemplate;
    //
    @Autowired
    StringRedisTemplate stringRedisTemplate;

    /**
     * 因为 @Cacheable(value = "llk") value需要传递的是常量，所以公共基础类没办法使用。不然缓存名称都是一样的了
     */
    @Autowired
    CacheManager cacheManager;

//    @Autowired
//    CacheManager cacheManager;

//    @CreateCache(area = "kevis",name="jetCache_",expire = 10,timeUnit = TimeUnit.MINUTES,serialPolicy = SerialPolicy.KRYO,keyConvertor = KeyConvertor.JACKSON)
//    private Cache<String ,Object> jetCache;

    private final String tableName = "";//this.getClass().getAnnotation(TableName.class).value();

    public String cacheKey = "你好:hello:123,dfg";

    public CommonClassServiceImpl(){
        //CacheName = "commonClass";
    }

    public List<T> selectByParentId(Function<LambdaQueryWrapper<T>, LambdaQueryWrapper<T>> queryWrapperFunction, Integer parentId, boolean isAllStatus) {
        LambdaQueryWrapper<T> wrapper = new LambdaQueryWrapper<>();
        // 使用提供的函数式接口修改LambdaQueryWrapper
        wrapper = queryWrapperFunction.apply(wrapper);
        if (parentId == null) parentId = 0;
        wrapper.eq(T::getParentId, parentId);
        if (!isAllStatus) {
            wrapper.eq(T::getStatus, 0);
        }
        return baseMapper.selectList(wrapper);
    }

    public List<T> selectByParentId(Integer parentId, boolean isAllStatus) {
        //LambdaQueryWrapper<T> wrapper = new LambdaQueryWrapper<>();
        QueryWrapper wrapper = new QueryWrapper();
        wrapper.eq("parent_id", parentId);
//        if(parentId == null)parentId=0;
//        wrapper.eq(T::getParentId,parentId);
//        if(!isAllStatus){
//            wrapper.eq(T::getStatus,0);
//        }
        return baseMapper.selectList(wrapper);
    }

    /**************************返回树形结构********************************/

    @Cacheable(value = "commonClass",keyGenerator = "selfKeyGenerate")
    public List<T> GetListTreeByParentId(int parentId, boolean isThis, boolean isAllStatus) {
//        System.out.println(cacheManager.getCache("users"));
//        System.out.println(redisTemplate);
//        System.out.println(stringRedisTemplate);
        return this.GetListTreeByParentId(parentId, isThis, isAllStatus, null);
    }

    @Cacheable(value = "commonClass",keyGenerator = "selfKeyGenerate")
    public List<T> GetListTreeByParentId(int parentId, boolean isThis, boolean isAllStatus, Integer classLevel) {
//        TableName tn = getTClass().getAnnotation(TableName.class);
//        tableName = tn.value();

        List<T> model = ToTree(parentId, GetListAll(), isThis, isAllStatus, classLevel);
        if (model == null) {
            return null;
        }
        return model;
    }

    private List<T> ToTree(int parentId, List<T> list, boolean isThis, boolean isAllStatus, Integer classLevel) {

//        Map<Integer, T> collectStu = list.stream().collect(Collectors.toMap(T::getId, Function.identity(), (key1, key2) -> key2));
//        for (Map.Entry<Integer, T> integerStudentEntry : collectStu.entrySet()) {
//            System.out.println(integerStudentEntry.getKey() + "::" + String.valueOf(integerStudentEntry.getValue()));
//        }
//
//        // 3.根据age作为key，student对象作为value分组转map（age相同时前面覆盖后面的数据）
//        Map<Integer, List<T>> listMap = list.stream().collect(Collectors.groupingBy(T::getId));
//        for (Map.Entry<Integer, List<T>> integerStudentEntry : listMap.entrySet()) {
//            System.out.println(integerStudentEntry.getKey() + "::" + String.valueOf(integerStudentEntry.getValue()));
//        }


        //定义字典类型，将List转换成字典类型，集合中的元素个数是相同的
        Map<Integer, T> map = new HashMap<Integer, T>();

        //是否只显示 有效数据
        if (!isAllStatus) {
            list = list.stream().filter(p -> p.getStatus() == 0).collect(Collectors.toList());
            //List = List.Where(t => (t as T_Base_Class).F_MarkStatus == 0).ToList();
        }

        if (classLevel != null) {
            list = list.stream().filter(p -> p.getClassLevel() <= classLevel).collect(Collectors.toList());
            //List = List.Where(t => (t as T_Base_Class).F_ParentLevels <= parentLevel).ToList();
        }

        for (T t : list) {
            map.put(t.getId(), t);
        }

        //通过一次遍历集合，转换成具有层次结构的类型
        for (T t : map.values()) {
            if (map.containsKey(t.getParentId())) {
                //创建子集对象
                if (map.get(t.getParentId()).getChildren() == null) {
                    map.get(t.getParentId()).setChildren(new ArrayList<>());
                }
                if (!Arrays.asList(map.get(t.getParentId()).getChildren()).contains(t)) {
                    map.get(t.getParentId()).getChildren().add(t);
                }
            }
        }

        //是否显示 自己
        if (isThis) {
            return map.values().stream().filter(t -> t.getId() == parentId).collect(Collectors.toList());
            //return dic.values().Where(t => (t as T_Base_Class).Id == ParentID).ToList();
        } else {
            return map.values().stream().filter(t -> t.getParentId() == parentId).collect(Collectors.toList());
            //return dic.Values.Where(t => (t as T_Base_Class).F_ParentID == ParentID).ToList();
        }
    }

    @Override
    public PageInfo<T> getPageList(CommonClassQuery query, PageDomain pageDomain) {
        return null;
    }

    public synchronized List<T> GetListAll() {
        List<T> entityList = null;
        //获取全部的数据的，需要给当前类调用的数据，由自己先缓存。不然本类调用，不会缓存这个全部数据
        Cache.ValueWrapper cacheValue = cacheManager.getCache(CacheName).get("GetListAll");
        if(cacheValue != null){
            entityList = ( List<T>)cacheValue.get();
        }

        //List<T> entityList = Get_Base_All_List();
        if (entityList == null || entityList.size() == 0) {
            entityList = baseMapper.selectList(null);
            if (entityList != null) {
                for (T _Item : entityList) {
                    if (_Item.getParentId() != 0) {
                        T _ClassItem = entityList.stream().filter(t2 -> t2.getId() == _Item.getParentId()).findAny().orElse(null);//.get();
                        //var _ClassItem = entityList.Where(t2 => (t2 as T_Base_Class).Id == _Item.F_ParentID).Select(t2 => t2).FirstOrDefault();
                        if (_ClassItem != null) {
                            _Item.setE_parentTitle(_ClassItem.getTitle());
                        } else {
                            _Item.setE_parentTitle("（错误）");
                        }
                    } else {
                        _Item.setE_parentTitle("（根目录）");
                    }
                }
                cacheManager.getCache(CacheName).put("GetListAll",entityList);
            }
//            jetCache.put("哎呦",entityList);
//            stringRedisTemplate.boundSetOps(cacheKey + ":sss").add("aaaass");
//            redisTemplate.boundHashOps("第一级").put("第二级", "你好啊");
//
            //如果速度太快，就会进来两次，然后存了两次，导致数据重复.所以这边还需要再次判断一下是不是真的没有。不过极端情况下，还是无法避免。最好就是不会失效。或者修改完重新覆盖？
//            if (Boolean.FALSE.equals(redisTemplate.hasKey(cacheKey))) {
//                redisTemplate.opsForList().leftPushAll(cacheKey, entityList);
//                redisTemplate.expire(cacheKey, 5, TimeUnit.MINUTES);
//            }
        }
        return entityList;
    }

    @Override
    public List<T> GetListByParentIn(int parentId, boolean isAllStatus) {
        return null;
    }

    public List<T> Get_Base_All_List() {
//        if (redisTemplate.hasKey(cacheKey)) {
//            return redisTemplate.opsForList().range(cacheKey, 0, -1);
//        }
        return null;
        //return (new CacheHelper()).Get(cacheKey) as List<TEntity>;
    }
}
